package system

import (
	"os"
	"path"
	"syscall"
)

//错误重定向的目标文件
var stdErrFileHandle *os.File

//进程锁
type NamedLock struct {
	f *os.File
}

//将os.Stderr写入文件
//linux下真实效果是所有stderr输出的消息转移到了文件
func StdErrorToFile(file *os.File) error {
	//延长生命周期
	_ = stdErrFileHandle
	stdErrFileHandle = file
	sh := os.Stderr.Fd()
	return syscall.Dup2(int(file.Fd()), int(sh))
}

//进程锁，加锁
func (l *NamedLock) Lock(name string) bool {
	shmPath := "/dev/shm"
	_, err := os.Stat(shmPath)
	if err != nil && os.IsNotExist(err) {
		os.MkdirAll(shmPath, 0666)
	}

	fullname := path.Join(shmPath, name)
	f, err := os.Open(fullname)
	if err != nil {
		f, err = os.Create(fullname)
		if err != nil {
			return false
		}
	}
	l.f = f
	err = syscall.Flock(int(f.Fd()), syscall.LOCK_EX|syscall.LOCK_NB)
	return err == nil
}

//进程锁，解锁
func (l *NamedLock) Unlock() {
	if l.f == nil {
		return
	}
	syscall.Flock(int(l.f.Fd()), syscall.LOCK_UN)
	l.f.Close()
}
